"""
作者 ： Levi
邮箱 ： lvze@tedu.cn
日期 ： 2021-5-17
环境 ： Python3.6

群聊聊天室，多进程网络的综合编码训练
"""
from socket import *
from multiprocessing import Process

# 服务器地址
HOST = "0.0.0.0"
PORT = 8888
ADDR = (HOST, PORT)

# 存储用户信息 {name:address}
user = {}


# 处理进入聊天室
def do_login(sock, name, address):
    if name in user or "管理" in name:
        sock.sendto(b'FAIL', address)
    else:
        sock.sendto(b'OK', address)
        msg = "欢迎 %s 进入聊天室" % name
        for key, value in user.items():
            sock.sendto(msg.encode(), value)
        user[name] = address  # 增加用户
    # print(user) #测试


# 消息转发给其他人　 name:　ｘｘｘｘ
def do_chat(sock, name, content):
    msg = "%s : %s" % (name, content)
    for key, value in user.items():
        if key != name:
            sock.sendto(msg.encode(), value)


def do_exit(sock, name):
    if name in user:
        del user[name]  # 删除用户
    msg = "%s 退出了群聊" % name
    for key, value in user.items():
        sock.sendto(msg.encode(), value)


# 子进程函数负责处理请求
def do_request(sock):
    # 循环接收请求
    while True:
        # 总体接受请求，根据请求类型分情况处理
        request, addr = sock.recvfrom(1024 * 1024)
        tmp = request.decode().split(' ', 2)
        if tmp[0] == "LOGIN":
            # tmp --> [LOGIN,name]
            do_login(sock, tmp[1], addr)
        elif tmp[0] == "CHAT":
            # tmp --> [CHAT,name,content]
            do_chat(sock, tmp[1], tmp[2])
        elif tmp[0] == "EXIT":
            # tmp --> [EXIT,name]
            do_exit(sock, tmp[1])


# 入口函数  实现网络通信
def main():
    sock = socket(AF_INET, SOCK_DGRAM)
    sock.bind(ADDR)

    # 创建进程
    p = Process(target=do_request, args=(sock,))
    p.start()

    #  父进程发送管理员消息
    while True:
        content = input("管理员消息：")
        msg = "CHAT 管理员消息 " + content
        sock.sendto(msg.encode(), ADDR)  # 父进程－》子进程


if __name__ == '__main__':
    main()
